package com.hup.utils.commons.swing;

import com.hup.utils.commons.hardware.ScreenUtil;
import com.hup.utils.commons.interfaces.Runners.Runner1;
import com.hup.utils.commons.start.LookThemeUtil;
import com.hup.utils.commons.start.StartupInfo;
import com.hup.utils.commons.thread.ThreadUtil;
import lombok.Setter;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.undo.UndoManager;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.CountDownLatch;

/**
 * @author hugan
 * @date 2020/3/25
 */
public class SimpleTestFrame extends JFrame implements SwingExecutable {

    /**
     * 解决junit进行界面测试时,窗口闪退问题;
     * true-调用show方法后,会锁住当前线程!
     */
    @Setter
    private static boolean isJUnit = true;

    public static void show(Runner1<SimpleTestFrame> runner) {
        show(runner, ScreenUtil.getScreenScale(100) / 100f);
    }

    public static void show(Runner1<SimpleTestFrame> runner, float scale) {
        StartupInfo.init();
        LookThemeUtil.initNormal(scale);
        SwingExecutable.initSwingExecutor();

        SimpleTestFrame frame = new SimpleTestFrame(StartupInfo.getApplicationName());
        runner.run(frame);

        frame.setVisible(true);

        if (isJUnit) {
            try {
                CountDownLatch latch = new CountDownLatch(1);
                latch.await();
            } catch (InterruptedException e) {
                ThreadUtil.handleInterruptedException(e);
            }
        }
    }

    public SimpleTestFrame(String title) {
        super(title);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setAlwaysOnTop(true);
        setSize(500, 280);
        locateToRightMid();
    }

    /**
     * 居右显示
     */
    public void locateToRightMid() {
        Insets coor = ScreenUtil.getScreenUsableCoor();
        int x = coor.right - getWidth();
        int y = (coor.bottom - coor.top - getHeight()) / 2;
        setLocation(x, y);
    }

    public void onExit(Runnable runnable) {
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                setVisible(false);
                runnable.run();
                dispose();
                System.exit(0);
            }
        });
    }

    @SuppressWarnings("Duplicates")
    public void initUndoText(JTextComponent c) {
        UndoManager undoManager = new UndoManager();
        Document document = c.getDocument();
        document.addUndoableEditListener(undoManager);
        c.setDocument(document);
        c.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                //第一次获取到焦点时,就重置undoManager(清空 程序初始化过程中改变过的文本),并移除本监听
                undoManager.discardAllEdits();
                c.removeFocusListener(this);
            }
        });

        c.registerKeyboardAction(e -> {
            if (undoManager.canUndo()) {
                int cursor = c.getSelectionStart();//恢复光标
                undoManager.undo();
                c.setSelectionStart(cursor);
                c.setSelectionEnd(cursor);
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        c.registerKeyboardAction(e -> {
            if (undoManager.canRedo()) {
                int cursor = c.getSelectionStart();//恢复光标
                undoManager.redo();
                c.setSelectionStart(cursor);
                c.setSelectionEnd(cursor);
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    }

    public static JButton addButton(String name, JPanel parent, ActionListener listener) {
        JButton button = new JButton(name);
        if (parent != null) parent.add(button);
        if (listener != null) button.addActionListener(listener);
        return button;
    }

}
